﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Autofac;
using SimpleData.ObjectModel;

namespace SimpleData.Infrastructure.Plugins
{
	/// <summary>
	/// Auxilia na construção e configuração dos plugins
	/// </summary>
	/// <typeparam name="TPluggable"></typeparam>
	public sealed class PlugConnectorBuilder<TPluggable>
		where TPluggable : IPluggable
	{
		private ContainerBuilder iocBuilder;

		/// <summary>
		/// 
		/// </summary>
		/// <param name="iocBuilder"></param>
		public PlugConnectorBuilder( ContainerBuilder iocBuilder )
		{
			this.iocBuilder = iocBuilder;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <typeparam name="TPlug"></typeparam>
		/// <returns></returns>
		public PlugConnectorBuilder<TPluggable> OnNew<TPlug>()
			where TPlug : TPluggable
		{
			this.iocBuilder
				.RegisterType<TPlug>()
				.As<TPluggable>()
				.InstancePerDependency();

			return this;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <typeparam name="TPlug"></typeparam>
		/// <returns></returns>
		public PlugConnectorBuilder<TPluggable> Once<TPlug>()
			where TPlug : TPluggable
		{
			this.iocBuilder
				.RegisterType<TPlug>()
				.As<TPluggable>()
				.SingleInstance();

			return this;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <typeparam name="TPlug"></typeparam>
		/// <param name="name"></param>
		/// <returns></returns>
		public PlugConnectorBuilder<TPluggable> Once<TPlug>( IDataObjectName name )
			where TPlug : TPluggable
		{
			this.iocBuilder
				.RegisterType<TPlug>()
				.Named<TPluggable>( name.FullName )
				.SingleInstance();

			return this;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <typeparam name="TPlug"></typeparam>
		/// <param name="plug"></param>
		/// <returns></returns>
		public PlugConnectorBuilder<TPluggable> WithThis<TPlug>( TPlug plug )
			where TPlug : class, TPluggable
		{
			this.iocBuilder
				.RegisterInstance( plug )
				.As<TPluggable>();

			return this;
		}
	}
}
